home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / macros / lamstex / index / index.c < prev    next >
C/C++ Source or Header  |  1991-09-06  |  60KB  |  2,690 lines

  1. /************************************************************************/
  2. /*   File:    Index.c                                */
  3. /************************************************************************/
  4. /*   Developer:    TeXplorators Inc., Houston, Texas                */
  5. /*   PRODUCT  :    Index: Sort TeX index entries alphabetically        */
  6. /*   Module   :    index                            */
  7. /*   Notes    :    This source code is compiled with Microsoft C 5.1       */
  8. /************************************************************************/
  9. /*
  10.             SOFTWARE LICENSE AGREEMENT
  11.  
  12. 1. PURPOSE
  13.     This agreement recites the terms and conditions under which 
  14. The TeXplorators Corporation ("TEXPLORATORS") agrees to grant you a 
  15. free, nonexclusive, transferable license to use the INDEX software.
  16.  
  17. 2. UNDERTAKINGS BY TEXPLORATORS
  18.     2A. Ownership: Ownership of the INDEX software remains 
  19. exclusively in TEXPLORATORS.
  20.     2B. License Fee: TEXPLORATORS makes the INDEX software 
  21. available to you free of any license fee.
  22.     2C. Disclaimers: TEXPLORATORS DISCLAIMS ALL EXPRESS OR IMPLIED
  23. WARRANTIES OF INDEX'S MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
  24. PURPOSE.
  25.     2D. Liability: TEXPLORATORS' LIABILITY, IF ANY, IS LIMITED TO 
  26. THE DISTRIBUTION FEE YOU PAID, AND DOES NOT INCLUDE SPECIAL AND/OR
  27. CONSEQUENTIAL DAMAGES ARISING OUT OF, OR IN CONNECTION WITH, THE USE 
  28. OF INDEX.  SINCE SOME STATES DISALLOW LIMITATION OR EXCLUSION OF 
  29. LIABILITY, THIS LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU.
  30.  
  31. 3. UNDERTAKINGS BY YOU.
  32.     3A. Proper Use: You agree to use the INDEX software in
  33. compliance with the terms and conditions hereof.
  34.     3B. Notices on Authorized Copies: You agree to take reasonable
  35. precautions to preserve the propriety of the INDEX software by
  36. duplicating verbatim, on all copies thereof, the notices of TEXPLORATORS'
  37. interests recited thereon.  You agree to note that source code is 
  38. available upon request, if you do not distribute source code with the
  39. INDEX software.
  40.     3C. Distribution: You are encouraged to freely distribute the
  41. INDEX software, including source code, on or through any common media
  42. including diskettes and electronic bulletin board systems.  You agree to
  43. distribute this license with each and every copy so distributed, and to 
  44. either distribute source code therewith or make source code available upon
  45. request. You may charge a distribution fee to cover the cost of diskettes,
  46. handling and shipping.
  47.     3D. Modifications: You are authorized to make modifications to
  48. INDEX, but these modifications must be conspicuously noted and dated
  49. therewith.
  50.     3E. License Fee: You may not charge a license fee for the
  51. INDEX software, either in its original or modified form.  However, you
  52. may charge a license fee for your software which is broader in scope
  53. than INDEX, whereby INDEX is not a primary functional unit thereof.
  54.  
  55. 4. SCOPE
  56.     This Software License Agreement constitutes the entire agreement
  57. between TEXPLORATORS and you regarding the INDEX software, and shall
  58. be construed under the laws of the State of TEXAS.
  59.  
  60.                     The TeXplorators Corporation
  61.                     By: Michael Spivak, President
  62.  
  63. Page*/
  64. /*
  65.   HISTORY:
  66.    [03/07/1991] - Index now operates on a single .ndx file - there will be
  67.                   .npg file. An error message will be issued if a
  68.                   \Page{...}{...}{...} does not follow each entry.
  69.                   Each entry buffer size is expanded to 300 symbols.
  70. */
  71.  
  72. /* Configuration and defines for Unix 05/08/1991, P. A. MacKay */
  73.  
  74. /* System-dependent defines */
  75. #include "config.h"
  76.  
  77. /*------------------------------*/
  78. /*    includes        */
  79. /*------------------------------*/
  80. #include  <stdio.h>
  81. #include  <ctype.h>
  82. #include  <malloc.h>    
  83. #include  <string.h>
  84. #ifdef ANSI
  85. #include  <stdlib.h>
  86. #endif
  87. #include  <memory.h>
  88.  
  89. /*------------------------------*/
  90. /*    defines            */
  91. /*------------------------------*/
  92.  
  93. #define TRUE        1
  94. #define FALSE       0
  95.  
  96. #define MAX_STRING    5120
  97. #define MAX_ENTRIES   15000
  98. #define MAX_DEFINES   200
  99. #define MAX_ABBREVS   200
  100. #define MAX_PAGEORDER 200
  101. #define MAX_PAGEENTRY 500
  102.  
  103. #define SPACE       32
  104. #define COMMA       ','
  105. #define STAR        '*'
  106. #define DQUOTE      34
  107. #define BAR         '|'
  108. #define LBRACE      123
  109. #define RBRACE      125
  110. #define RSLASH        '\\'
  111. #define MINUS       '-'
  112. #define PLUS        '+'
  113. #define NL        '\n'
  114. #define LBRACKET    '['
  115. #define RBRACKET    ']'
  116. #define LPAREN      '('
  117. #define RPAREN      ')'
  118. #define QUOTE       39
  119. #define DOLLAR      '$'
  120. #define ATSIGN      '@'
  121. #define TILDE       '~'
  122. #define EXCLAIM     '!'
  123. #define CARET       '^'
  124. #define USCORE      '_'
  125. #define EQUAL       '='
  126. #define COLON       ':'
  127. #define SEMI        ';'
  128. #define LQUOTE      '`'
  129. #define GREATER     '>'
  130. #define LESS        '<'
  131. #define QUESTION    '?'
  132. #define SLASH       '/'
  133. #define PERIOD      '.'
  134.  
  135. #define ZERO        '0'
  136. #define ONE         '1'
  137. #define TWO        '2'
  138. #define THREE       '3'
  139. #define FOUR        '4'
  140. #define FIVE        '5'
  141.  
  142. #define ENTRY1       1
  143. #define ENTRY2       4
  144. #define ENTRY3       7
  145. #define ENTRY4      10
  146. #define ENTRY5      13
  147.  
  148. #define PRE_TYPE     0
  149. #define POST_TYPE    1
  150. #define ALIAS_TYPE   2
  151. #define ENTRY_TYPE   3
  152. #define XREF_TYPE    4
  153. #define CROSS_TYPE   5
  154. #define OTHER_TYPE   6
  155.  
  156. #define LEVEL0        0
  157. #define LEVEL1        1
  158. #define LEVEL2        2
  159. #define LEVEL3        3
  160. #define LEVEL4        4
  161. #define LEVEL5        5
  162.  
  163. #define E1            1
  164. #define E1_PRE        2
  165. #define E1_POST       3
  166. #define E1_ALIAS     23
  167. #define E1_CS        28
  168.  
  169. #define E2            4
  170. #define E2_PRE        5
  171. #define E2_POST       6
  172. #define E2_ALIAS     24
  173. #define E2_CS        29
  174.  
  175. #define E3            7
  176. #define E3_PRE        8
  177. #define E3_POST       9
  178. #define E3_ALIAS     25
  179. #define E3_CS        30
  180.  
  181. #define E4           10
  182. #define E4_PRE       11
  183. #define E4_POST      12
  184. #define E4_ALIAS     26
  185. #define E4_CS        31
  186.  
  187. #define E5           13
  188. #define E5_PRE       14
  189. #define E5_POST      15
  190. #define E5_ALIAS     27
  191. #define E5_CS        32
  192.  
  193. #define XREF         16
  194. #define NUMBER       17
  195. #define CSNAME       18
  196. #define PREFIX       19
  197. #define POSTFIX      20
  198. #define PAGE_SPAN    21
  199. #define LARGEST      22
  200. #define CTRLSEQ      33
  201. #define CROSS_REF    34
  202.  
  203. /*------------------------------*/
  204. /*    typedefs        */
  205. /*------------------------------*/
  206. #ifdef MICROSOFT_C
  207. typedef unsigned int   WORD;
  208. #else
  209. typedef unsigned short   WORD;
  210. #endif
  211. typedef unsigned char  BYTE;
  212.  
  213. typedef struct
  214. {
  215.   char *fields[35];
  216. } FieldType;
  217.  
  218. typedef struct
  219. {
  220.   FieldType *item;
  221. } EntryType;
  222.  
  223. typedef struct
  224. {
  225.   char *astr;
  226.   char *xstr;
  227. } AbbrvType;
  228.  
  229. typedef struct
  230. {
  231.   char *style;
  232.   char *pre;
  233.   char *post;
  234.   BYTE order;
  235.   BYTE nstyle;
  236.   BYTE npre;
  237.   BYTE npost;
  238. } PageOrderType;
  239.  
  240. /*------------------------------*/
  241. /*    data structures        */
  242. /*------------------------------*/
  243. EntryType Entry[MAX_ENTRIES];    /* entries            */
  244. char      *define[MAX_DEFINES];    /* defines            */
  245. AbbrvType *abbrev[MAX_ABBREVS];    /* abbrevs            */
  246. PageOrderType *PO[MAX_PAGEORDER];/*page orders            */
  247. int       SubPageOrder[MAX_PAGEENTRY];
  248. int       SortingOrder[35];     /* sorting order indices    */
  249. int       FirstOrder;        /* First Sorting Order entry*/
  250. int       LastOrder;        /* Last Sorting Order entry */
  251. int       PageOrder[10];        /* Page order indices       */
  252. int       PageOrderFirst;    /* Fist page order entry    */
  253. int       PageOrderLast;    /* Last page order entry    */
  254. char      PageType;        
  255. int       PageIndex;
  256. int       PageSpan;
  257. int       Tindex;        /* Topage Index         */
  258. char      string[300];        /* working string buffer    */
  259. FILE      *ndxfile;        /* index file            */
  260. FILE      *xdxfile;        /* sorted file            */
  261. FILE      *xxxfile;        /* temporary file        */
  262. char      ndxname[80];        /* .ndx file name        */
  263. char      xdxname[80];        /* .xdx file name        */
  264. char      tmpname[80];        /* .@d@ file name        */
  265. char      idxname[80];        /* .idx file name        */
  266. BYTE      alias;        /* alias flag            */
  267. BYTE      xref;            /* xref flag            */
  268. BYTE      crossref;        /* crossref flag            */
  269. BYTE      curEntry;        /* type of entry appears    */
  270. WORD      nitems;        /* number of input lines    */
  271. WORD      ndef;         /* number of defs        */
  272. WORD      nabb;            /* number of abbrevs        */
  273. WORD      npo;            /* number of pageorders        */
  274. char      curLetter;        /* current letter        */
  275. char      preLetter;        /* previous letter        */
  276. BYTE      FirstEntry;        /* first entry flag        */
  277. char      pagenum[80];        /* page number            */
  278. char      prevnum[80];        /* previous page number        */
  279. BYTE      skippage;        /* skip page flag        */
  280. char      *nullstr="";        /* NULL string            */
  281. char      *NULLPTR;        /* NULL pointer            */
  282. char      *delstr="D";        /* Delete string        */
  283. char      *DELPTR;        /* DEL pointer            */
  284. BYTE      idxfile;              /* make idxfile            */
  285. char      msgbuf[1024];         /* message buffer        */
  286. int       curIndex;        /* current index        */
  287. char      arg1[300], arg2[300], arg3[300], arg4[300], arg5[300];
  288.  
  289. /*------------------------------*/
  290. /*    functions prototypes    */
  291. /*------------------------------*/
  292. #ifdef ANSI /* Use ANSI C prototypes */
  293. void  beep(void);
  294. void  BuildProc(void);
  295. void  BuildString(int);
  296.  
  297. char *CheckAbbrev(char s[], char *q);
  298. void  CheckAlias(int);
  299. BYTE  CheckLevel(int cur, int idx, BYTE level);
  300. int   CompareStrings(int i,int j);
  301. int   CompareStringsPO(int i,int j);
  302. void  copyString(int,int,char *);
  303.  
  304. void  doNDX(int,char *);
  305. void  doNPG(int,char *);
  306. void  DoNormal(int idx,char arg[]);
  307. void  DoVariant(int idx, char arg[]);
  308. int   DupPageFormat(int idx, char arg[]);
  309. int   DupEntry(int idx, int cur);
  310. int   DupXref(int idx, int cur);
  311.  
  312. void  error(char *);
  313. void  exit(int);
  314.  
  315. int   FindLastT( int idx );
  316. void  FreeEntry( int idx );
  317. void  FreeMem(void);
  318.  
  319. void  GetAbbrevSpace(int);
  320. void  GetArg(int idx,char arg[],BYTE pre,BYTE cs,BYTE entry,
  321.              BYTE post,BYTE alias);
  322. void  GetArgs(int idx,char *arg1,char *arg2,char *arg3,
  323.               char *arg4,char *arg5);
  324. BYTE  GetD2(int cur,int idx);
  325. void  GetFieldSpace(int);
  326. BYTE  GetPageNum(int idx);
  327. int   GetPageOrder(int);
  328. void  GetPageOrderSpace(int);
  329. char *GetStringSpace(char *);
  330. int   GetSubLevel(int, int);
  331.  
  332. void  InitProc(void);
  333.  
  334. void  OutputProc(int idx,char *arg1,char *arg2,char *arg3,
  335.                  char *arg4,char *arg5);
  336.  
  337. int  main(int argc, char *argv[]);
  338. void  MoveEntry( int from, int to );
  339.  
  340. void  PreProc(void);
  341. void  printMSG(char *);
  342. void  PrintErrorMSG(void);
  343. void  PutPageNum(int idx);
  344. void  PutByte( char c, FILE *f );
  345. void  PutString( char string[], FILE *f );
  346.  
  347. void  ReduceSpaces(char *);
  348. void  RemoveDuplicates( void );
  349. void  RemoveEmptySet(char *str);
  350. void  RemoveSpaces(char *);
  351. void  RemoveTrailingSpace(char *str);
  352.  
  353. void  ScanEntry( char line[] );
  354. char *SkipSpaces(char *p);
  355. void  SkipSpacesReverse(int len, char *p);
  356. void  SortPageNumber( int beg, int end );
  357. void  SortProc(void);
  358. void  strCopy(char *,char *,int);
  359. void  SwapStrings(int cur, int nxt);
  360. void  syntax_error(char *);
  361.  
  362. void  TeXOut(void);
  363. void  TeXPut(int idx);
  364.  
  365. void  xref_proc(int idx);
  366. void  xxref_proc(int idx);
  367. void  other_proc(int idx);
  368. #else
  369. /* Use old-style K&R function declarations */
  370. void  beep();
  371. void  BuildProc();
  372. void  BuildString();
  373.  
  374. char *CheckAbbrev();
  375. void  CheckAlias();
  376. BYTE  CheckLevel();
  377. int   CompareStrings();
  378. int   CompareStringsPO();
  379. void  copyString();
  380.  
  381. void  doNDX();
  382. void  doNPG();
  383. void  DoNormal();
  384. void  DoVariant();
  385. int   DupPageFormat();
  386. int   DupEntry();
  387. int   DupXref();
  388.  
  389. void  error();
  390. void  exit();
  391.  
  392. int   FindLastT();
  393. void  FreeEntry();
  394. void  FreeMem();
  395.  
  396. void  GetAbbrevSpace();
  397. void  GetArg();
  398. void  GetArgs();
  399. BYTE  GetD2();
  400. void  GetFieldSpace();
  401. BYTE  GetPageNum();
  402. int   GetPageOrder();
  403. void  GetPageOrderSpace();
  404. char *GetStringSpace();
  405. int   GetSubLevel();
  406.  
  407. void  InitProc();
  408.  
  409. void  OutputProc();
  410.  
  411. int main();
  412. void  MoveEntry();
  413.  
  414. void  PreProc();
  415. void  printMSG();
  416. void  PrintErrorMSG();
  417. void  PutPageNum();
  418. void  PutByte();
  419. void  PutString();
  420.  
  421. void  ReduceSpaces();
  422. void  RemoveDuplicates();
  423. void  RemoveEmptySet();
  424. void  RemoveSpaces();
  425. void  RemoveTrailingSpace();
  426.  
  427. void  ScanEntry();
  428. char *SkipSpaces();
  429. void  SkipSpacesReverse();
  430. void  SortPageNumber();
  431. void  SortProc();
  432. void  strCopy();
  433. void  SwapStrings();
  434. void  syntax_error();
  435.  
  436. void  TeXOut();
  437. void  TeXPut();
  438.  
  439. void  xref_proc();
  440. void  xxref_proc();
  441. void  other_proc();
  442. #endif
  443.  
  444. /*------------------------------*/
  445. /*    functions         */
  446. /*------------------------------*/
  447.  
  448. void beep()
  449. {
  450.    printf("\007\b");
  451.    return;
  452. }
  453.  
  454. void FreeMem()
  455. {
  456. int i,j;
  457.    for (i=0; i<=nitems; i++)
  458.    {
  459.      if ( Entry[i].item!=NULL )
  460.      {
  461.        for (j=E1; j<=CROSS_REF; j++)
  462.        {
  463.     if (Entry[i].item->fields[j]!=NULLPTR )
  464.         free( Entry[i].item->fields[j] );
  465.        }
  466.      }
  467.    }
  468.    for (i=0; i<MAX_DEFINES; i++)
  469.     if ( define[i]!=NULL )
  470.          free( define[i] );
  471.    for (i=0; i<MAX_ABBREVS; i++)
  472.     if ( abbrev[i]!=NULL )
  473.     {
  474.          if ( abbrev[i]->astr != NULL ) free( abbrev[i]->astr );
  475.          if ( abbrev[i]->xstr != NULL ) free( abbrev[i]->xstr );
  476.          free( abbrev[i] );
  477.     }
  478.     
  479.    for (i=0; i<MAX_PAGEORDER; i++)
  480.     if ( PO[i]!=NULL )
  481.     {
  482.          if ( PO[i]->style !=NULL ) free( PO[i]->style );
  483.          if ( PO[i]->pre   !=NULL ) free( PO[i]->pre );
  484.          if ( PO[i]->post  !=NULL ) free( PO[i]->post );
  485.          free( PO[i] );
  486.         }
  487.  
  488.    return;
  489. }
  490.  
  491. void error(s)
  492. char *s;
  493. {
  494.    beep();    
  495.    printf("\n%s\n",s);
  496.    FreeMem();
  497.    exit(0);
  498. }
  499.  
  500. void syntax_error(s)
  501. char *s;
  502.   sprintf(string,"syntax error! -> %s",s);
  503.   error(string); 
  504. }
  505.  
  506.  
  507. void printMSG(s)
  508. char *s;
  509. {
  510.    int i;
  511.    printf("\r");
  512.    for (i=0; i<78; i++)
  513.        printf(" ");
  514.    printf("\r");
  515.    printf("%s",s);
  516.    return;
  517. }
  518.  
  519.  
  520. void PutByte(c,f)
  521.  char c; 
  522.  FILE *f;
  523. {
  524.   fputc( c, f );
  525.   if ( ferror(f) )
  526.        error("! File write error - out of disk space");
  527. } /* end - PutByte */
  528.  
  529.  
  530. void PutString(s,f)
  531.  char *s; 
  532.  FILE *f;
  533. {
  534.    fputs( s, f );
  535.    if ( ferror(f) )
  536.        error("! File write error - out of disk space");
  537. } /* end  - PutString */
  538.  
  539. /* Get Field Space */
  540. void GetFieldSpace(idx)
  541. int  idx;
  542. {
  543. int  i;
  544.    
  545.    /* Check for boundary conditions */
  546.    if ( idx >= MAX_ENTRIES )
  547.    {
  548.       sprintf(string,"! number of entries (%d) exceeded MAXIMUM allowed (%d)",
  549.           idx,MAX_ENTRIES);
  550.       error( string );
  551.    }
  552.    
  553.    Entry[idx].item = (FieldType *) malloc( sizeof(FieldType) );
  554.    if ( Entry[idx].item==NULL )
  555.     error("! out of fields space");
  556.    for (i=0; i<35; i++)
  557.     Entry[idx].item->fields[i]=NULLPTR;
  558.    return;
  559. }
  560.  
  561.  
  562. /* Get Abbrev Space */
  563. void GetAbbrevSpace(idx)
  564. int  idx;
  565. {
  566.    /* Check for boundary conditions */
  567.    if ( idx >= MAX_ABBREVS )
  568.    {
  569.       sprintf(string,"! number of abbrevs (%d) exceeded MAXIMUM allowed (%d)",
  570.           idx,MAX_ABBREVS);
  571.       error( string );
  572.    }
  573.    
  574.    abbrev[idx] = (AbbrvType *) malloc( sizeof(AbbrvType) );
  575.    if ( abbrev[idx]==NULL )
  576.     error("! out of space");
  577.    abbrev[idx]->astr = NULL;
  578.    abbrev[idx]->xstr = NULL;
  579.    return;
  580. }
  581.  
  582. /* Get PageOrder Space */
  583. void GetPageOrderSpace(idx)
  584. int  idx;
  585. {
  586.  
  587.    /* Check for boundary conditions */
  588.    if ( idx >= MAX_PAGEORDER )
  589.    {
  590.       sprintf(string,
  591.       "! number of pageorders directives (%d) exceeded MAXIMUM allowed (%d)",
  592.           idx,MAX_PAGEORDER);
  593.       error( string );
  594.    }
  595.   
  596.    PO[idx] = (PageOrderType *) malloc( sizeof(PageOrderType) );
  597.    if ( PO[idx]==NULL )
  598.     error("! out of space");
  599.    PO[idx]->style = NULL;
  600.    PO[idx]->pre   = NULL;
  601.    PO[idx]->post  = NULL;
  602.    PO[idx]->order    = 0;
  603.    PO[idx]->nstyle   = 0;
  604.    PO[idx]->npre     = 0;
  605.    PO[idx]->npost    = 0;
  606.    return;
  607. }
  608.  
  609.  
  610. /* Get String Space */
  611. char * GetStringSpace(str)
  612. char *str;
  613. {
  614. char *p;
  615. int  i;
  616.    i = strlen(str);
  617.    p = (char *) malloc( i+1 );
  618.    if ( p==NULL )
  619.     error("! out of strings space");
  620.    return(p);
  621. }
  622.  
  623.  
  624. void InitProc()
  625. {
  626.   int i;
  627.   for (i=0; i<MAX_ENTRIES; i++)
  628.        Entry[i].item = NULL;
  629.   for (i=0; i<MAX_DEFINES; i++)
  630.        define[i] = NULL;
  631.   for (i=0; i<MAX_ABBREVS; i++)
  632.        abbrev[i] = NULL;
  633.   for (i=0; i<MAX_PAGEORDER; i++)
  634.        PO[i] = NULL;
  635.   FirstEntry = TRUE;    
  636.   NULLPTR    = &nullstr[0];
  637.   PageType   = 0;
  638.   PageIndex  = 0;
  639.   PageSpan   = FALSE;
  640.   Tindex     = 0;
  641.   
  642.   SortingOrder[1] =E1;
  643.   SortingOrder[2] =E1_ALIAS;
  644.   SortingOrder[3] =E1_PRE;
  645.   SortingOrder[4] =E1_POST;
  646.   
  647.   SortingOrder[5] =E2;
  648.   SortingOrder[6] =E2_ALIAS;
  649.   SortingOrder[7] =E2_PRE;
  650.   SortingOrder[8] =E2_POST;
  651.   
  652.   SortingOrder[9] =E3;
  653.   SortingOrder[10]=E3_ALIAS; 
  654.   SortingOrder[11]=E3_PRE;
  655.   SortingOrder[12]=E3_POST;
  656.   
  657.   SortingOrder[13]=E4;  
  658.   SortingOrder[14]=E4_ALIAS;
  659.   SortingOrder[15]=E4_PRE;
  660.   SortingOrder[16]=E4_POST;
  661.   
  662.   SortingOrder[17]=E5;
  663.   SortingOrder[18]=E5_ALIAS;  
  664.   SortingOrder[19]=E5_PRE;  
  665.   SortingOrder[20]=E5_POST;
  666.   SortingOrder[21]=CROSS_REF;
  667.  
  668.   FirstOrder = 1;
  669.   LastOrder  = 21;
  670.  
  671.   PageOrder[0] = CSNAME;
  672.   PageOrder[1] = PREFIX;
  673.   PageOrder[2] = NUMBER;
  674.   PageOrder[3] = POSTFIX;
  675.  
  676.   PageOrderFirst = 0;
  677.   PageOrderLast  = 3;
  678.   
  679.   return;
  680. }
  681.  
  682. void ReduceSpaces(str)
  683. char *str;
  684. {
  685.    char *p;
  686.    char *q;
  687.  
  688.    p = str; q = str;
  689.    while ( *p != 0 )
  690.    {
  691.       if ( (*p == SPACE) && (*(p+1) == SPACE) ) p++;
  692.       else
  693.           *q++ = *p++;
  694.    }
  695.    *q = *p;
  696.    return;
  697. }
  698.  
  699.  
  700. void BuildString(idx)
  701. int idx;
  702. {
  703.   int  i;
  704.   char cbuf[300];
  705.   char str[300];
  706.  
  707.   string[0] = 0;
  708.   for (i=E1; i<NUMBER; i++)
  709.   {
  710.     switch( i )
  711.     {
  712.       case 2: case 5: case 8: case 11: case 14:
  713.       case 3: case 6: case 9: case 12: case 15:    
  714.        if ( Entry[idx].item->fields[i]!=NULLPTR )
  715.        {
  716.                 memcpy(cbuf,Entry[idx].item->fields[i],
  717.                    strlen(Entry[idx].item->fields[i])+1);
  718.        }
  719.        else cbuf[0]=0;
  720.        sprintf(str,"%s %c",cbuf,BAR);
  721.        strcat(string,str);
  722.        break;
  723.       default:
  724.        if ( Entry[idx].item->fields[i]!=NULLPTR )
  725.                 memcpy(cbuf,Entry[idx].item->fields[i],
  726.                strlen(Entry[idx].item->fields[i])+1);
  727.        else cbuf[0] = 0;
  728.        sprintf(str,"%s %c",cbuf,BAR);
  729.        ReduceSpaces(&str[0]);    
  730.        strcat(string,str);
  731.        break;
  732.       }
  733.   }
  734.   
  735.   for (i=NUMBER; i<=CROSS_REF; i++)
  736.   {
  737.     if ( Entry[idx].item->fields[i]!=NULLPTR )
  738.          memcpy(cbuf,Entry[idx].item->fields[i], 
  739.             strlen(Entry[idx].item->fields[i])+1);
  740.     else cbuf[0]=0;
  741.     sprintf(str,"%s%c",cbuf,BAR);
  742.     ReduceSpaces(&str[0]);    
  743.     strcat(string,str);
  744.   }
  745.  
  746.   return;
  747. }
  748.  
  749. int GetSubLevel(n,op)
  750. int n,op;
  751. {
  752. int  cur;    
  753.    switch ( op )
  754.    {
  755.      case 'a':   cur = 22 + n; curEntry = ALIAS_TYPE; alias = TRUE; 
  756.           break;
  757.      case MINUS: cur = n*3 -1; curEntry = PRE_TYPE; 
  758.           break;
  759.      case PLUS:  cur = n*3;    curEntry = POST_TYPE; 
  760.           break;
  761.      case 'e':   cur = 27 + n; curEntry = ENTRY_TYPE; 
  762.           break;
  763.      default:    cur = 0; 
  764.           break;
  765.    }
  766.   return(cur);
  767. }
  768.  
  769. void CheckAlias(idx)
  770. int idx;
  771. {
  772. char *p;
  773.  
  774.    if ( Entry[idx].item->fields[E1_ALIAS]!=NULLPTR )
  775.    {
  776.        p = Entry[idx].item->fields[E1];
  777.        Entry[idx].item->fields[E1] = Entry[idx].item->fields[E1_ALIAS];
  778.        Entry[idx].item->fields[E1_ALIAS] = p;
  779.    }
  780.  
  781.    if ( Entry[idx].item->fields[E2_ALIAS]!=NULLPTR )
  782.    {
  783.        p = Entry[idx].item->fields[E2];
  784.        Entry[idx].item->fields[E2] = Entry[idx].item->fields[E2_ALIAS];
  785.        Entry[idx].item->fields[E2_ALIAS] = p;
  786.    }
  787.  
  788.    if ( Entry[idx].item->fields[E3_ALIAS]!=NULLPTR )
  789.    {
  790.        p = Entry[idx].item->fields[E3];
  791.        Entry[idx].item->fields[E3] = Entry[idx].item->fields[E3_ALIAS];
  792.        Entry[idx].item->fields[E3_ALIAS] = p;
  793.    }
  794.  
  795.    if ( Entry[idx].item->fields[E4_ALIAS]!=NULLPTR )
  796.    {
  797.        p = Entry[idx].item->fields[E4];
  798.        Entry[idx].item->fields[E4] = Entry[idx].item->fields[E4_ALIAS];
  799.        Entry[idx].item->fields[E4_ALIAS] = p;
  800.    }
  801.  
  802.    if ( Entry[idx].item->fields[E5_ALIAS]!=NULLPTR )
  803.    {
  804.        p = Entry[idx].item->fields[E5];
  805.        Entry[idx].item->fields[E5] = Entry[idx].item->fields[E5_ALIAS];
  806.        Entry[idx].item->fields[E5_ALIAS] = p;
  807.    }
  808.    return;    
  809. }
  810.  
  811.  
  812. void strCopy(d,s,len)
  813. char *d, *s;
  814. int  len;
  815. {
  816. int  i;
  817.    for (i=0; i<=len; i++)
  818.         *(d+i) = *(s+i);
  819.    return;    
  820. }
  821.  
  822. void copyString(idx,cur,str)
  823. int  idx,cur;
  824. char *str;
  825. {
  826.  if ( cur == 0 ) return;    
  827.     Entry[idx].item->fields[cur] = GetStringSpace( str );
  828.     strcpy(Entry[idx].item->fields[cur], str );
  829.     return;    
  830. }
  831.  
  832. char *SkipSpaces(p)
  833. char *p;
  834. {
  835.    while ( *p==SPACE && *p!=0 ) p++;    
  836.    return(p);    
  837. }
  838.  
  839. void SkipSpacesReverse(len,q)
  840. int  len;
  841. char *q;
  842. {
  843.    char *r;
  844.  
  845.    r = q-2;
  846.    while ( *r==SPACE && len>0 ) 
  847.    { r--; len--; }
  848.    r++; *r = 0;
  849.    
  850.    return;    
  851. }
  852.  
  853. void RemoveSpaces(str)
  854. char *str;
  855. {
  856.    char *p;
  857.    char *q;
  858.  
  859.    p = q = str; 
  860.    while ( *p != 0 )
  861.    {
  862.       if ( (*p == SPACE) ) p++;
  863.       else
  864.           *q++ = *p++;
  865.    }
  866.    *q = *p;
  867.    return;
  868. }
  869.  
  870. void RemoveEmptySet(str)
  871. char *str;
  872. {
  873.    char *p;
  874.    char *q;   
  875.  
  876.    if ( strlen(str) <= 2 ) return;
  877.    p = str; q = str;
  878.    while ( *p != 0 )
  879.    {
  880.       if ( (*p == LBRACE) && (*(p+1) == RBRACE) ) p+=2;
  881.       else
  882.           *q++ = *p++;
  883.    }
  884.    *q = *p;
  885.    return;
  886. }
  887.  
  888. void RemoveTrailingSpace(str)
  889. char *str;
  890. {
  891.    char *p;
  892.    char *q;
  893.  
  894.    p = str; q = str;
  895.    while ( *p != 0 )
  896.    {
  897.       if ( (*p == SPACE) && (*(p+1) == RBRACE) ) p++;
  898.       else
  899.           *q++ = *p++;
  900.    }
  901.    *q = *p;
  902.    return;
  903. }
  904.  
  905. void doNDX(idx,str)
  906. int  idx;
  907. char str[];
  908. {
  909.    int  i,j;
  910.    char *p, *q, *r;
  911.    int  cur,e;
  912.    BYTE done;
  913.  
  914.    j = strlen(str);
  915.    p = &str[0]; p++; q = r = &string[0];
  916.    i = 0; e = 1; cur = E1;
  917.    xref = FALSE; alias = FALSE; crossref = FALSE;
  918.    done = FALSE; curEntry = OTHER_TYPE;
  919.    while ( !done && i<j )
  920.    {
  921.       switch ( *p )
  922.       {
  923.     case DQUOTE:
  924.          if ( *(p-1)==RSLASH ) 
  925.                   *q++ = *p;        
  926.          else
  927.          done = TRUE;
  928.          break;
  929.         case NL:
  930.          done = TRUE;
  931.          break;
  932.         case STAR:
  933.              *q++ = 0; 
  934.              if ( cur!=0 )
  935.          {
  936.                SkipSpacesReverse(j,q);
  937.            copyString(idx,cur,string); 
  938.            cur = 0;
  939.              }
  940.          q = r; 
  941.          p++; i++;
  942.              switch ( *p )
  943.          {
  944.            case ONE: case TWO: case THREE: case FOUR: case FIVE:
  945.             cur = GetSubLevel( (*p)-ZERO,*(p+1) ); p++; i++;
  946.                 q = r;
  947.             break;
  948.                case 'a':  
  949.             p++; i++; q = r;
  950.             curEntry = ALIAS_TYPE;
  951.             alias = TRUE;
  952.             cur = E1_ALIAS;
  953.             break;
  954.             case MINUS:
  955.             p++; i++; q = r;
  956.                 curEntry = PRE_TYPE;
  957.             cur = E1_PRE;
  958.             break;
  959.             case PLUS:
  960.              p++; i++; q = r;
  961.                  curEntry = POST_TYPE;
  962.              cur = E1_POST;
  963.              break;
  964.            case 'e': 
  965.             q = r;
  966.             curEntry = ENTRY_TYPE;
  967.             cur = E1_CS;
  968.             break;
  969.            case 'p': 
  970.             q = r;
  971.                 cur = CTRLSEQ;
  972.             break;
  973.            case 'f':  
  974.            case 'F':
  975.            case 't': 
  976.             q = r;
  977.             *q++ = *p; *q++ = 0;
  978.             copyString(idx,PAGE_SPAN,string);
  979.             q = r;
  980.             break;
  981.            case 'x': 
  982.             if ( crossref )
  983.             {
  984.                sprintf(msgbuf,"%s\n *x and *X can't occur together\n",
  985.                    str);
  986.                syntax_error(msgbuf);
  987.                 }
  988.                 strcpy(string,"x");    copyString(idx,XREF,string);
  989.             strcpy(string,"99999"); copyString(idx,NUMBER,string);
  990.             curEntry = XREF_TYPE; xref = TRUE;
  991.             q = r;
  992.             cur = CROSS_REF;
  993.             break;
  994.           case 'X':
  995.             if ( xref )
  996.             {
  997.                sprintf(msgbuf,"%s\n *x and *X can't occur together\n",
  998.                    str);
  999.                syntax_error(msgbuf);
  1000.                 }
  1001.                    strcpy(string,"X");  copyString(idx,XREF,string);
  1002.            crossref = TRUE;
  1003.                cur = CROSS_REF; curEntry = XREF_TYPE;
  1004.            q = r;
  1005.            break;
  1006.           case RSLASH:
  1007.             cur = 0; break;
  1008.           default: 
  1009.             syntax_error(str);
  1010.             cur = 0;
  1011.                 break;
  1012.          }
  1013.          break;
  1014.         case COMMA:
  1015.              p++; i++; *q++ = 0;
  1016.              copyString(idx,cur,string);
  1017.          q = r;
  1018.          e++; cur = e*3 - 2;
  1019.          break;
  1020.        case LBRACE:
  1021.         switch ( curEntry )
  1022.         {
  1023.         case ALIAS_TYPE:    
  1024.         case PRE_TYPE:
  1025.         case POST_TYPE:
  1026.         case ENTRY_TYPE:
  1027.         case XREF_TYPE:
  1028.         case CROSS_TYPE:            
  1029.              break;
  1030.             default:
  1031.              *q++ = *p; break;
  1032.         }
  1033.         break;
  1034.        case RBRACE: 
  1035.         switch ( curEntry )
  1036.         {
  1037.         case ALIAS_TYPE:    
  1038.              alias = FALSE; 
  1039.         case PRE_TYPE:
  1040.         case POST_TYPE:
  1041.         case ENTRY_TYPE:
  1042.         case XREF_TYPE:
  1043.         case CROSS_TYPE:            
  1044.                      *q++ = 0; 
  1045.                      ReduceSpaces(string);
  1046.                  copyString(idx,cur,string); 
  1047.                  q = r; 
  1048.              curEntry = OTHER_TYPE; cur = 0;
  1049.              break;
  1050.             default:
  1051.              *q++ = *p; break;
  1052.         }
  1053.         break;
  1054.        case RSLASH:
  1055.         if ( *(p+1) == COMMA)
  1056.             {
  1057.            p++; i++; *q++ = *p;
  1058.         }
  1059.         else
  1060.           *q++ = *p;
  1061.             break;
  1062.        default:
  1063.         *q++ = *p;
  1064.         break;
  1065.        }
  1066.        p++; i++;
  1067.     }
  1068.    
  1069.    *q++ = 0;
  1070.    if ( cur!=0 )
  1071.    {
  1072.       SkipSpacesReverse(j,q);
  1073.       copyString(idx,cur,string); 
  1074.       cur = 0;
  1075.    }
  1076.  
  1077.    /* post processing of ndxfile */
  1078.    /* largest j with <entry_j>    */
  1079.    sprintf(string,"%d",e);
  1080.    copyString(idx,LARGEST,string);
  1081.  
  1082.    CheckAlias(idx);
  1083.    
  1084.    return;    
  1085. }
  1086.  
  1087.  
  1088. void doNPG(idx,str)
  1089. int  idx;
  1090. char str[];
  1091. {
  1092.    int  i,j,k;
  1093.    char *p, *q, *r;
  1094.    int  cur;
  1095.    char num[10],outstr[10];
  1096.  
  1097.    j = strlen(str);
  1098.    p = &str[0]; p++; q = r = &string[0]; i = 0; 
  1099.    while ( *p != RBRACE && i<j ) 
  1100.    {
  1101.       num[i++] = *p++;
  1102.    }
  1103.    num[i] = 0;
  1104.    strcpy(outstr,"0000");
  1105.    for (k=i; k>=0; k--)
  1106.    outstr[4-i+k] = num[k];
  1107.    for (k=0; k<5; k++)
  1108.    outstr[k];
  1109.    copyString(idx,NUMBER,outstr);
  1110.  
  1111.    p++; i++; cur = CSNAME; 
  1112.    while ( i<j && *p != NL )
  1113.    {
  1114.       switch ( *p )
  1115.       {
  1116.        case LBRACE:
  1117.         if ( *(p+1) != RBRACE )
  1118.              q = r;
  1119.         else { p++; i++; cur++; }
  1120.         break;
  1121.        case RBRACE: 
  1122.         *q++ = 0;
  1123.         copyString(idx,cur,string);
  1124.         cur++;
  1125.         break;
  1126.        default:
  1127.         *q++ = *p;
  1128.         break;
  1129.        }
  1130.        p++; i++;
  1131.    }
  1132.    return;    
  1133. }
  1134.  
  1135. char * CheckAbbrev(s,q)
  1136. char s[];
  1137. char *q;
  1138. {
  1139.   int  i,j,len;
  1140.   BYTE found;
  1141.   char *p;
  1142.   
  1143.   for (i=0, found=FALSE; i<nabb && !found; i++)
  1144.   {
  1145.     if ( stricmp(s,abbrev[i]->astr)==0 )
  1146.     {
  1147.     found = TRUE; p = abbrev[i]->xstr; len = strlen(abbrev[i]->xstr); 
  1148.     j = 0;
  1149.     while ( *p!=0 && j<len) 
  1150.     {
  1151.        *q++ = *p++; j++;
  1152.     }
  1153.     }
  1154.   }
  1155.   if ( !found )
  1156.   { sprintf(string,"syntax error! '%s' - not an \\abbrev",s); error(string); }
  1157.   return ( q );
  1158. }
  1159.  
  1160.  
  1161.  
  1162. /* preprocess NDX file for defines, abbrevs, page orders */
  1163. void PreProc()
  1164. {
  1165.    char buf[300],str[300];
  1166.    int    i,j,len;
  1167.    char *p, *q, *r;
  1168.    BYTE done, status;
  1169.  
  1170.    printMSG("preprocessing...");
  1171.    ndef = nabb = npo = 0 ;
  1172.    fgets(buf,300,ndxfile);
  1173.    while ( !feof(ndxfile) )
  1174.    {  
  1175.      len = strlen(buf);
  1176.      p = &buf[0];
  1177.      if ( strnicmp(p,"\\define",7)==0 )
  1178.      {
  1179.        buf[len-1]=0;
  1180.        if ( ndef >= MAX_DEFINES )
  1181.        {
  1182.       sprintf(string,
  1183.           "! number of defines (%d) exceeded MAXIMUM allowed (%d)",
  1184.           ndef,MAX_DEFINES);
  1185.       error( string );
  1186.        }
  1187.        define[ndef] = GetStringSpace(p);
  1188.        strcpy(define[ndef],p);
  1189.        ndef++;
  1190.      }
  1191.      else
  1192.      {
  1193.     if ( strnicmp(p,"\\abbrev",7)==0 )
  1194.     {
  1195.        buf[len-1]=0; p+=7;
  1196.        GetAbbrevSpace(nabb);
  1197.        j=0; q  = &buf[len-1];
  1198.  
  1199.        i=0;  /* remove spaces */
  1200.        while ( *p==SPACE && i<len )
  1201.        { p++; i++; }
  1202.  
  1203.        while ( *(p+j)!=LBRACE && *(p+j)!=SPACE && (p+j)<q ) j++; 
  1204.        *(p+j) = 0;
  1205.        abbrev[nabb]->astr = GetStringSpace(p);
  1206.        strcpy(abbrev[nabb]->astr,p);
  1207.  
  1208.        p += j+1; j = len-1;
  1209.        i=0;  /* remove spaces */
  1210.        while ( *p==SPACE && i<len )
  1211.        { p++; i++; }
  1212.  
  1213.        if ( *p==LBRACE ) p++;
  1214.        
  1215.        while ( *q!=RBRACE && q>p ) q--;
  1216.        *q = 0;
  1217.        abbrev[nabb]->xstr = GetStringSpace(p);
  1218.        strcpy(abbrev[nabb]->xstr,p);
  1219.        nabb++;
  1220.     }
  1221.     else
  1222.     {
  1223.            i=0;  /* remove spaces */
  1224.        while ( *p==SPACE && i<len )
  1225.        { p++; i++; }
  1226.      
  1227.        if ( strnicmp(p,"\\pageorder",10)==0 )
  1228.        {
  1229.          buf[len-1]=0; 
  1230.          p+=10;
  1231.          RemoveSpaces(p);
  1232.          GetPageOrderSpace(npo);
  1233.          /* get style */
  1234.          j=0; q  = &buf[len-1];
  1235.          while ( *(p+j)!=LBRACE && (p+j)<q ) 
  1236.          {   j++; }
  1237.          if ( (p+j) >= q )
  1238.            syntax_error(buf);
  1239.          *(p+j) = 0;
  1240.          PO[npo]->style = GetStringSpace(p);
  1241.          strcpy(PO[npo]->style,p);
  1242.          PO[npo]->nstyle = (BYTE) strlen(p);
  1243.  
  1244.          /* get pre page material */
  1245.          p += j+1; j=0;
  1246.          while ( *(p+j)!=RBRACE && (p+j)<q ) j++; 
  1247.          if ( (p+j) >= q )
  1248.         syntax_error(buf);
  1249.          *(p+j) = 0;
  1250.          if ( j==0 )
  1251.          { PO[npo]->pre = NULLPTR;  }
  1252.          else
  1253.          { PO[npo]->pre = GetStringSpace(p); strcpy(PO[npo]->pre,p); }
  1254.          PO[npo]->npre = (BYTE) strlen(p);
  1255.  
  1256.          /* get post page material */
  1257.          p += j+2; j=0;
  1258.          while ( *(p+j)!=RBRACE && (p+j)<q ) j++; 
  1259.          if ( (p+j) >= q )
  1260.         syntax_error(buf);
  1261.          *(p+j) = 0;
  1262.          if ( j==0 )
  1263.          { PO[npo]->post = NULLPTR; }
  1264.          else
  1265.          { PO[npo]->post = GetStringSpace(p); strcpy(PO[npo]->post,p); }
  1266.          PO[npo]->npost = (BYTE) strlen(p);
  1267.          
  1268.          /* get page order */
  1269.          p += j+1; 
  1270.          if ( *p==LBRACE ) 
  1271.          {    p++; q--; *q=0;  }
  1272.          PO[npo]->order =(BYTE) atoi(p);
  1273.          npo++;
  1274.            } /* endif page order */
  1275.        else
  1276.        {
  1277.         if ( *p!=NL && *p!=SPACE )
  1278.         {
  1279.          q = &string[0];
  1280.          done = FALSE; status = FALSE; i = 0;
  1281.          *q++ = *p++;
  1282.          while ( i<len )
  1283.          {
  1284.          switch ( *p )
  1285.          {
  1286.            case STAR:
  1287.             if ( *(p+1)==RSLASH )
  1288.             {
  1289.               r = &str[0]; done = FALSE;
  1290.               *r++ = *p++; *r++ = *p++;
  1291.               while ( !done )
  1292.               {
  1293.                switch ( *p )
  1294.                    {
  1295.             case SPACE: case DQUOTE: case COMMA: case LBRACE:
  1296.             case RBRACE: case LBRACKET: case RBRACKET:
  1297.             case LPAREN: case RPAREN: case QUOTE: case DOLLAR:
  1298.             case TILDE: case EXCLAIM: case CARET:
  1299.             case MINUS: case USCORE: case PLUS: case EQUAL:
  1300.             case COLON: case SEMI: case LQUOTE: case GREATER:
  1301.             case LESS: case QUESTION: case SLASH: case BAR:
  1302.             case STAR: case RSLASH: case PERIOD:
  1303.                  *r++=0;
  1304.                  done = TRUE;
  1305.                  break;
  1306.                 default:
  1307.                  *r++ = *p++; i++;
  1308.                      break;
  1309.                    } /* switch */
  1310.                   }  /* while */
  1311.               q=CheckAbbrev(str,q);
  1312.             } /* if */
  1313.             else
  1314.             {  *q++ = *p++; i++; }
  1315.             break;
  1316.            default:
  1317.             *q++ = *p++; i++;
  1318.             break;
  1319.          } /* switch */
  1320.           } /* while */
  1321.       *q++ = 0;
  1322.       PutString( string, xxxfile );
  1323.           } /* not NL or SPACE */
  1324.         } /* others */
  1325.        } /* else pageorders */
  1326.      } /* else abbrevs */
  1327.      fgets(buf,300,ndxfile);
  1328.    } /* while */
  1329.    return;    
  1330. }
  1331.  
  1332.  
  1333.  
  1334.  
  1335. /**********************************************************************/
  1336. /* BuildProc: read in contents of .ndx file into internal data buffers*/
  1337. /* Inputs   : .ndx file handle                                        */
  1338. /* Output   : Entries                                                 */
  1339. /**********************************************************************/
  1340. #ifndef SEEK_END
  1341. #define SEEK_END 2
  1342. #define SEEK_CUR 1
  1343. #define SEEK_SET 0
  1344. #endif
  1345. void BuildProc( void )
  1346. {
  1347.    char abuf[300];
  1348.    char bbuf[300];
  1349.    int  i;
  1350.  
  1351.    fseek(xxxfile, 0L, SEEK_SET);
  1352.    nitems = 0;
  1353.    fgets(abuf,300,xxxfile);
  1354.    while( !feof(xxxfile) )
  1355.    {
  1356.       nitems++;
  1357.       fgets( abuf,300,xxxfile );
  1358.    }
  1359.  
  1360.    nitems/=2;
  1361.    fseek(xxxfile, 0L, SEEK_SET);
  1362.    GetFieldSpace(0);
  1363.  
  1364.    for (i=1; i<=nitems; i++ )
  1365.    {
  1366.      fgets(abuf,300,xxxfile);
  1367.      fgets(bbuf,300,xxxfile);
  1368.      
  1369.      if ( bbuf[0]!='{' )
  1370.      {
  1371.           sprintf( msgbuf,"\n! Entry ->\n%s does not have a following \"{...}{...}{...}\" line.", abuf );
  1372.       error( msgbuf );
  1373.      }
  1374.      
  1375.      GetFieldSpace(i);
  1376.      ScanEntry( abuf );
  1377.      doNDX(i,abuf);    
  1378.      doNPG(i,bbuf);
  1379.      
  1380.    };
  1381.  
  1382.    return;
  1383. }
  1384.  
  1385.  
  1386.  
  1387. /**********************************************************************/
  1388. /* ScanEntry: scan entry line and delete entry delimiters             */
  1389. /* Inputs   : line                                                    */
  1390. /* Output   : line                                                    */
  1391. /**********************************************************************/
  1392. void ScanEntry( char line[] )
  1393. {
  1394. int   len,i;
  1395.   if ( line[0] == RSLASH )
  1396.   {
  1397.      sprintf( msgbuf,"Entry ->\n%s begins with a '\\'.", line );
  1398.      error( msgbuf );
  1399.   }
  1400.   else
  1401.     line[0] = SPACE;
  1402.   
  1403.   len = strlen( line );
  1404.   i = strlen(line) - 2;
  1405.   while( i>0 && line[i] == SPACE )
  1406.   {
  1407.     i--;
  1408.   }
  1409.   line[i] = SPACE;
  1410.   line[i] = NL;
  1411.   return;
  1412.   
  1413. }
  1414.  
  1415.  
  1416.  
  1417. int PageOrderSort(i,j)
  1418. int i, j;
  1419. {
  1420. int stat,n,k;
  1421. int i_order, j_order;
  1422.  
  1423.     i_order=GetPageOrder(i);
  1424.     j_order=GetPageOrder(j);
  1425.  
  1426.     stat = 0;
  1427.     for (n=PageOrderFirst; n<=PageOrderLast && stat==0; n++)
  1428.     {
  1429.      k = PageOrder[n];
  1430.      stat=strcmp(Entry[i].item->fields[k],Entry[j].item->fields[k]);
  1431.      switch ( k )
  1432.      {    
  1433.            case CSNAME:
  1434.        case PREFIX:
  1435.          if ( stat!= 0 ) 
  1436.          {
  1437.            if ( i_order < j_order ) return( -1 );
  1438.            if ( i_order > j_order ) return(  1 );
  1439.            return ( stat );
  1440.              }
  1441.              break;
  1442.        case NUMBER:
  1443.          if ( stat != 0 ) 
  1444.          {
  1445.           if ( (i_order == j_order) && (i_order == MAX_PAGEORDER) )
  1446.                return( stat );
  1447.           if ( (i_order == MAX_PAGEORDER) && (j_order < i_order) )
  1448.                return( 1 );
  1449.               if ( (j_order == MAX_PAGEORDER) && (i_order < j_order) )
  1450.                return( -1 );
  1451.           return( stat );
  1452.          }
  1453.          else
  1454.          {
  1455.             if ( i_order < j_order ) return( -1 );
  1456.             if ( i_order > j_order ) return(  1 );
  1457.          }
  1458.          break;
  1459.        case POSTFIX:
  1460.          if ( stat!= 0 ) 
  1461.          {
  1462.            if ( i_order < j_order ) return( -1 );
  1463.            if ( i_order > j_order ) return(  1 );
  1464.            return ( stat );
  1465.              }
  1466.              break;
  1467.        default:
  1468.              break;
  1469.         } /* switch */
  1470.  
  1471.      } /* for */
  1472.    return( stat );    
  1473. }
  1474.  
  1475. int CompareStrings(i,j)
  1476. int  i,j;
  1477. {
  1478. int n,k;    
  1479. int stat;
  1480.  
  1481.    stat=0;
  1482.    for (n=FirstOrder; n<=LastOrder && stat==0; n++)
  1483.    {
  1484.      k = SortingOrder[n];
  1485.      stat=stricmp(Entry[i].item->fields[k],Entry[j].item->fields[k]);
  1486.    }
  1487.  
  1488.    if ( stat==0 )
  1489.    {
  1490.       stat = PageOrderSort(i,j);
  1491.    } /* if */
  1492.    
  1493.    return( stat );
  1494. }
  1495.  
  1496.  
  1497. int GetPageOrder(idx)
  1498. int idx;
  1499. {
  1500. int i,done;    
  1501. int order;
  1502.    order = MAX_PAGEORDER;
  1503.    for (i=0,done=FALSE; i<npo && !done; i++)
  1504.    {
  1505.      if (  strncmp(Entry[idx].item->fields[CSNAME],PO[i]->style,
  1506.                 PO[i]->nstyle)==0
  1507.     && strncmp(Entry[idx].item->fields[PREFIX],PO[i]->pre,
  1508.             PO[i]->npre)==0
  1509.     && strncmp(Entry[idx].item->fields[POSTFIX],PO[i]->post,
  1510.             PO[i]->npost)==0 )
  1511.      {
  1512.        order = PO[i]->order; done = TRUE;
  1513.      }
  1514.    }
  1515.    return(order);
  1516. }
  1517.  
  1518.  
  1519. void SwapStrings(cur,nxt)
  1520. int  cur,nxt;
  1521. {
  1522.    int   k;
  1523.    char *p;
  1524.    for (k=E1; k<=CROSS_REF; k++)
  1525.    {
  1526.     p = Entry[cur].item->fields[k];
  1527.     Entry[cur].item->fields[k] = Entry[nxt].item->fields[k];
  1528.     Entry[nxt].item->fields[k] = p;
  1529.    }
  1530.    return;
  1531. }
  1532.  
  1533. void SortProc()
  1534. {
  1535. int  i,j,n;
  1536. FILE *f;
  1537. int  gap;
  1538.  
  1539.   printMSG("sorting...");
  1540.   
  1541.   /* Shell sort */
  1542.   n = nitems+1;
  1543.   for ( gap=n/2; gap>0; gap/=2 )
  1544.   {
  1545.      for ( i=gap; i<n; i++ )
  1546.      {
  1547.     for ( j=i-gap; j>0 && CompareStrings(j,j+gap) > 0; j-=gap )
  1548.     {
  1549.         SwapStrings(j,j+gap);
  1550.     }
  1551.      }
  1552.   }
  1553.   
  1554.   /* write out sorted list - this is for debugging only */
  1555.   if ( idxfile )
  1556.   {
  1557.     f = fopen(idxname,"w");
  1558.     if ( f==NULL )
  1559.     { sprintf(string,"File write error %s",idxname); error(string); }
  1560.     for (i=1; i<=nitems; i++)
  1561.     { 
  1562.     BuildString(i); 
  1563.     PutString( string, f ); PutByte( NL, f);
  1564.     }
  1565.     fclose(f);
  1566.   }
  1567.  
  1568.   return;    
  1569. }
  1570.  
  1571.  
  1572. int CompareStringsPO(i,j)
  1573. int  i,j;
  1574. {
  1575. int stat;
  1576.    stat = PageOrderSort(i,j);
  1577.    return( stat );
  1578. }
  1579.  
  1580.  
  1581. /**********************************************************************/
  1582. /* Sort Page Numbers                                              */
  1583. /* Inputs: beginning entry, ending entry                              */
  1584. /* Output: Sorted list of page numbers entries                        */
  1585. /**********************************************************************/
  1586. void SortPageNumber(beg,end)
  1587.  int beg, end;
  1588. {
  1589. int  i,j,k,n;
  1590. int  change,status;
  1591.  
  1592.   /* Check for boundary conditions */
  1593.   if ( ( end - beg )  >= MAX_PAGEENTRY )
  1594.   {
  1595.      sprintf(string,"! page line entries (%d) exceeded MAXIMUM allowed (%d)",
  1596.          end-beg,MAX_PAGEENTRY );
  1597.      error( string );
  1598.   }
  1599.   
  1600.   n = 0;
  1601.   for (i=beg; i<end; i++)
  1602.   {
  1603.      if ( *(Entry[i].item->fields[XREF])!='x' )
  1604.      {
  1605.        SubPageOrder[n] = i; n++;
  1606.      }
  1607.   }
  1608.  
  1609.   /* Refined Bubble sort - for simplicity  
  1610.      Note: we only need to sort a subset of the entries. 
  1611.            Sorting is done using an array of indices without
  1612.        physically swapping entries. */
  1613.   change = TRUE;    
  1614.   for (i=0; i<n && change; i++)
  1615.   {
  1616.      change = FALSE;
  1617.      for (j=0;j<n-1;j++)
  1618.      {
  1619.        status = CompareStringsPO(SubPageOrder[j],SubPageOrder[j+1]);
  1620.        if ( status>0 )
  1621.        { 
  1622.      k = SubPageOrder[j+1];
  1623.      SubPageOrder[j+1] = SubPageOrder[j];
  1624.      SubPageOrder[j] = k;
  1625.      change=TRUE; }
  1626.      }
  1627.   }
  1628.  
  1629.   return;
  1630. }
  1631.  
  1632.  
  1633. BYTE CheckLevel(cur,idx,level)
  1634. int  cur,idx;
  1635. BYTE level;
  1636. {
  1637. BYTE entry_i, pre_i, post_i, alias_i, cs_i;
  1638.  
  1639.   switch ( level )
  1640.   {
  1641.      case LEVEL1:
  1642.           entry_i = E1; pre_i = E1_PRE; post_i = E1_POST;
  1643.           alias_i = E1_ALIAS; cs_i = E1_CS;
  1644.       break;
  1645.      case LEVEL2:
  1646.           entry_i = E2; pre_i = E2_PRE; post_i = E2_POST;
  1647.           alias_i = E2_ALIAS; cs_i = E2_CS;
  1648.       break;
  1649.      case LEVEL3:
  1650.           entry_i = E3; pre_i = E3_PRE; post_i = E3_POST;
  1651.           alias_i = E3_ALIAS; cs_i = E3_CS;
  1652.       break;
  1653.      case LEVEL4:
  1654.           entry_i = E4; pre_i = E4_PRE; post_i = E4_POST;
  1655.           alias_i = E4_ALIAS; cs_i = E4_CS;
  1656.       break;
  1657.      case LEVEL5:
  1658.           entry_i = E5; pre_i = E5_PRE; post_i = E5_POST;
  1659.           alias_i = E5_ALIAS; cs_i = E5_CS;
  1660.       break;
  1661.   }
  1662.  
  1663.   if (  strcmp(Entry[cur].item->fields[entry_i],
  1664.     Entry[idx].item->fields[entry_i])==0
  1665.      && strcmp(Entry[cur].item->fields[pre_i],
  1666.     Entry[idx].item->fields[pre_i])  ==0
  1667.      && strcmp(Entry[cur].item->fields[post_i],
  1668.     Entry[idx].item->fields[post_i]) ==0
  1669.      && strcmp(Entry[cur].item->fields[alias_i],
  1670.     Entry[idx].item->fields[alias_i])==0
  1671.      && strcmp(Entry[cur].item->fields[cs_i],
  1672.     Entry[idx].item->fields[cs_i])   ==0
  1673.      )
  1674.      return(TRUE); 
  1675.   else
  1676.      return(FALSE);
  1677. }
  1678.  
  1679.  
  1680. BYTE GetD2(cur,idx)
  1681. int  cur;
  1682. int  idx;
  1683. {
  1684.   if ( CheckLevel( cur,idx,LEVEL1 ) )
  1685.   {
  1686.       if ( CheckLevel( cur,idx,LEVEL2 ) )    
  1687.       {
  1688.           if ( CheckLevel( cur,idx,LEVEL3)  )
  1689.       {
  1690.          if ( CheckLevel( cur,idx,LEVEL4 ) )
  1691.          {
  1692.          if ( CheckLevel ( cur,idx,LEVEL5 ) )
  1693.               return(LEVEL5);
  1694.              else return(LEVEL4);
  1695.          }
  1696.          else return(LEVEL3);
  1697.       }
  1698.       else return(LEVEL2);
  1699.       }
  1700.       else return(LEVEL1);
  1701.    }
  1702.    else return(LEVEL0);
  1703.  
  1704.    return(LEVEL0);    
  1705. }
  1706.  
  1707.  
  1708.  
  1709.  
  1710. void GetArg(idx,arg,pre,cs,entry,post,alias)
  1711. int  idx;
  1712. char arg[];
  1713. BYTE pre,cs,entry,post,alias;
  1714. {
  1715.    if ( Entry[idx].item->fields[alias]!=NULLPTR )
  1716.      entry = alias;
  1717.  
  1718.    if ( Entry[idx].item->fields[cs]==NULLPTR )
  1719.    {
  1720.        if ( Entry[idx].item->fields[pre]==NULLPTR
  1721.      && Entry[idx].item->fields[post]==NULLPTR )
  1722.             sprintf(arg,"{%s}",Entry[idx].item->fields[entry]);
  1723.        else
  1724.            sprintf(arg,"{{%s}{%s}{%s}}",Entry[idx].item->fields[pre],
  1725.            Entry[idx].item->fields[entry],Entry[idx].item->fields[post]);
  1726.    }
  1727.    else
  1728.    {
  1729.        sprintf(arg,"{{%s}{%s{%s}}{%s}}",Entry[idx].item->fields[pre],
  1730.            Entry[idx].item->fields[cs],
  1731.            Entry[idx].item->fields[entry],Entry[idx].item->fields[post]);
  1732.    }
  1733.  
  1734.    RemoveEmptySet(arg);
  1735.  
  1736.    return;
  1737. }
  1738.  
  1739.  
  1740. void DoNormal(idx,arg)
  1741. int  idx;
  1742. char arg[];
  1743. {
  1744. char *p;
  1745. char str[80];
  1746. int  pn;
  1747.  
  1748.    pn = atoi(Entry[idx].item->fields[NUMBER]);
  1749.    strcpy( str, Entry[idx].item->fields[CSNAME] );
  1750.    p = &str[0];
  1751.    if ( strncmp(p,"\\arabic",7)==0 ) *p=0;
  1752.  
  1753.    if ( Entry[idx].item->fields[CTRLSEQ]==NULLPTR )
  1754.    {
  1755.       if ( Entry[idx].item->fields[PREFIX]==NULLPTR
  1756.     && Entry[idx].item->fields[POSTFIX]==NULLPTR )
  1757.       {
  1758.       if ( *p==0 )
  1759.              sprintf(arg,"{%d}",pn);
  1760.           else
  1761.              sprintf(arg,"{%s{%d}}",p,pn);          
  1762.       }
  1763.       else
  1764.       {  
  1765.       if ( *p==0 )
  1766.               sprintf(arg,"{{%s}{%d}{%s}}",
  1767.                   Entry[idx].item->fields[PREFIX],pn,
  1768.               Entry[idx].item->fields[POSTFIX]);
  1769.       else
  1770.               sprintf(arg,"{{%s}{%s{%d}}{%s}}",
  1771.                       Entry[idx].item->fields[PREFIX],p,pn,
  1772.               Entry[idx].item->fields[POSTFIX]);
  1773.       }
  1774.    }
  1775.    else
  1776.    {
  1777.       if ( Entry[idx].item->fields[PREFIX]==NULLPTR 
  1778.     && Entry[idx].item->fields[POSTFIX]==NULLPTR )
  1779.       {
  1780.       if ( *p == 0 )
  1781.                sprintf(arg,"{%s{%d}}",Entry[idx].item->fields[CTRLSEQ],pn);
  1782.           else
  1783.                sprintf(arg,"{%s{%s{%d}}}",Entry[idx].item->fields[CTRLSEQ],
  1784.                p,pn);
  1785.       }
  1786.       else
  1787.       {
  1788.       if ( *p == 0 )
  1789.               sprintf(arg,"{%s{{%s}{%d}{%s}}}",
  1790.                   Entry[idx].item->fields[CTRLSEQ],
  1791.                       Entry[idx].item->fields[PREFIX],pn,
  1792.               Entry[idx].item->fields[POSTFIX]);
  1793.       else
  1794.              sprintf(arg,"{%s{{%s}{%s{%d}}{%s}}}",
  1795.              Entry[idx].item->fields[CTRLSEQ],
  1796.                      Entry[idx].item->fields[PREFIX],p,pn,
  1797.              Entry[idx].item->fields[POSTFIX]);
  1798.       }
  1799.    }
  1800.    return;
  1801. }
  1802.  
  1803.  
  1804. void DoVariant(idx,arg)
  1805. int  idx;
  1806. char arg[];
  1807. {
  1808. char *p;
  1809. int  pn;
  1810. char str[80];
  1811.  
  1812.    pn = atoi(Entry[idx].item->fields[NUMBER]);
  1813.    strcpy(str,Entry[idx].item->fields[CSNAME]);
  1814.    p = &str[0];
  1815.    if ( strncmp(p,"\\arabic",7)==0 ) *p=0;
  1816.  
  1817.    if ( Entry[idx].item->fields[PREFIX]==NULLPTR 
  1818.      && Entry[idx].item->fields[POSTFIX]==NULLPTR )
  1819.    {
  1820.       if ( *p==0 )
  1821.          sprintf(arg,"{%s }{%d}",Entry[idx].item->fields[CTRLSEQ],pn);
  1822.       else
  1823.          sprintf(arg,"{%s }{%s{%d}}",Entry[idx].item->fields[CTRLSEQ],p,pn);
  1824.    }
  1825.    else
  1826.    {  
  1827.       if ( *p==0 )
  1828.            sprintf(arg,"{%s }{{%s}{%d}{%s}}",
  1829.                Entry[idx].item->fields[CTRLSEQ],
  1830.                    Entry[idx].item->fields[PREFIX],pn,
  1831.                Entry[idx].item->fields[POSTFIX]);
  1832.       else
  1833.            sprintf(arg,"{%s }{{%s}{%s{%d}}{%s}}",
  1834.                Entry[idx].item->fields[CTRLSEQ],
  1835.            Entry[idx].item->fields[PREFIX],
  1836.                p,pn,Entry[idx].item->fields[POSTFIX]);
  1837.    }
  1838.    return;
  1839. }
  1840.  
  1841.  
  1842. void  PrintErrorMSG()
  1843. {
  1844. int i;
  1845.  
  1846.    PutString( "%% ",xdxfile );
  1847.    for (i=0; i<72; i++) 
  1848.     PutByte('/',xdxfile);
  1849.    PutByte( NL, xdxfile );
  1850.    PutString("%%\n",xdxfile);
  1851.    PutString( msgbuf,xdxfile );
  1852.    PutString("%%\n",xdxfile);
  1853.    PutString("%% ",xdxfile); 
  1854.    for (i=0; i<72; i++) 
  1855.     PutByte('\\',xdxfile);
  1856.    PutByte( NL, xdxfile);
  1857.  
  1858.    return;
  1859. }
  1860.  
  1861.  
  1862. int DupPageFormat(idx,arg)
  1863. int idx;
  1864. char arg[];
  1865. {
  1866. int  i,level;
  1867. BYTE done;
  1868. char tmpbuf[300];
  1869.  
  1870.   for (i=idx-1, done=FALSE; i>0 && !done; i--)
  1871.   {
  1872.     level = GetD2(i,idx);
  1873.     if ( level==LEVEL5 ) 
  1874.     {
  1875.       if ( strcmp(Entry[idx].item->fields[NUMBER],
  1876.             Entry[i].item->fields[NUMBER])==0 
  1877.     &&  strcmp(Entry[idx].item->fields[CTRLSEQ],
  1878.                Entry[i].item->fields[CTRLSEQ])!=0 )
  1879.       {
  1880.        RemoveEmptySet(arg);
  1881.        sprintf(msgbuf,"%%  \\Page %s\n",arg);
  1882.        sprintf(tmpbuf,
  1883.         "%%  Duplicate page number formatted differently\n");
  1884.        strcat(msgbuf,tmpbuf);
  1885.        PrintErrorMSG();
  1886.        done = TRUE;
  1887.        return( FALSE );
  1888.      } /* if */
  1889.    } /* if - level */
  1890.    else 
  1891.       done = TRUE;
  1892.   } /* for */
  1893.   return(TRUE);
  1894. }
  1895.  
  1896.  
  1897. /**********************************************************************/
  1898. /* Find The Last matching t entry                                     */
  1899. /* Inputs: index into current entry                                   */
  1900. /* Output: TRUE if found, FALSE if not                                */
  1901. /**********************************************************************/
  1902. int FindLastT(idx)
  1903. int idx;
  1904. {
  1905. int i,level,done;
  1906.  
  1907.   Tindex = 0; done = FALSE; 
  1908.   level = GetD2(idx-1,idx);
  1909.   for ( i=idx-1;
  1910.         ( i>0 ) && ( level==LEVEL5 ) && !done ;
  1911.     i-- )
  1912.   {
  1913.     done = TRUE;
  1914.     if (   strcmp(Entry[idx].item->fields[NUMBER],
  1915.                  Entry[i].item->fields[NUMBER])==0 
  1916.     && strcmp(Entry[idx].item->fields[PAGE_SPAN],
  1917.                  Entry[i].item->fields[PAGE_SPAN])==0 )
  1918.     {
  1919.        Tindex = i; done = FALSE;
  1920.     }
  1921.     level = GetD2(i-1,idx);
  1922.     
  1923.   }
  1924.  
  1925.   if ( Tindex != 0 )
  1926.        return( TRUE );
  1927.   else
  1928.        return( FALSE );
  1929.  
  1930. }
  1931.  
  1932.  
  1933.  
  1934. BYTE GetPageNum(idx)
  1935. int  idx;
  1936. {
  1937. char type;
  1938. char arg[300];
  1939. int  status;
  1940. char tmpbuf[300];
  1941.  
  1942.    type = *(Entry[idx].item->fields[PAGE_SPAN]); skippage = FALSE;
  1943.    switch ( type )
  1944.    {
  1945.      case 'F':
  1946.     DoVariant(idx,arg);
  1947.     if ( PageType=='f' || PageType=='F' )
  1948.     {
  1949.           sprintf(msgbuf,"%%  \\Pagespan %s\n",arg);
  1950.       sprintf(tmpbuf,
  1951.               "%%  Page span starting at %s within span starting at %d\n",
  1952.           arg,atoi(Entry[PageIndex].item->fields[NUMBER]));    
  1953.       strcat(msgbuf,tmpbuf);
  1954.       PrintErrorMSG();
  1955.       skippage = TRUE;
  1956.       return(FALSE);
  1957.     }
  1958.     
  1959.     PageType = type ; PageIndex = idx;
  1960.         PageSpan = TRUE;
  1961.     break;
  1962.   case 'f': 
  1963.       DoNormal(idx,arg);      
  1964.       if ( PageType=='f' || PageType=='F' )
  1965.       {
  1966.        sprintf(msgbuf,"%%  \\Pagespan %s\n",arg);
  1967.        sprintf(tmpbuf,
  1968.            "%%  Page span starting at %s within span starting at %d\n",
  1969.             arg,atoi(Entry[PageIndex].item->fields[NUMBER]));    
  1970.        strcat(msgbuf,tmpbuf);
  1971.        PrintErrorMSG();
  1972.        skippage = TRUE;
  1973.        return(FALSE);
  1974.       }
  1975.       
  1976.       PageType = type ; PageIndex = idx;
  1977.       PageSpan = TRUE;
  1978.     break;
  1979.   case 't':
  1980.     switch ( PageType ) 
  1981.     {
  1982.       case 'F': 
  1983.     DoVariant(idx,arg); 
  1984.         break;
  1985.       case 'f': 
  1986.     DoNormal(idx,arg); 
  1987.         break;
  1988.       default: 
  1989.     DoNormal(idx,arg); 
  1990.  
  1991.         if ( FindLastT(idx)  )
  1992.     {
  1993.      sprintf(msgbuf,"%%  \\Topage %s\n",arg);
  1994.      sprintf(tmpbuf,
  1995.             "%%  Span ending at %s also ending at {%s {%d}}\n",
  1996.         arg,
  1997.         Entry[Tindex].item->fields[CTRLSEQ],
  1998.         atoi(Entry[Tindex].item->fields[NUMBER]));
  1999.      strcat(msgbuf,tmpbuf);
  2000.      PrintErrorMSG();
  2001.      skippage = TRUE;
  2002.          PageType = 0; PageIndex = 0; PageSpan = FALSE;
  2003.      return(FALSE); 
  2004.     }
  2005.     
  2006.     sprintf(msgbuf,"%%  \\Topage %s\n",arg);
  2007.     sprintf(tmpbuf,
  2008.             "%%  Page span ending at %s has no starting page\n",
  2009.         arg);
  2010.     strcat(msgbuf,tmpbuf);
  2011.     PrintErrorMSG();
  2012.     skippage = TRUE;
  2013.         PageType = 0; PageIndex = 0; PageSpan = FALSE;       
  2014.     return(FALSE); 
  2015.       break;
  2016.     } /* switch */
  2017.  
  2018.     break;
  2019.   default: 
  2020.      DoNormal(idx,arg); 
  2021.      if ( PageSpan )
  2022.      {
  2023.        /* Drop it if within page span */
  2024.        status = stricmp(Entry[idx].item->fields[CTRLSEQ],
  2025.                     Entry[PageIndex].item->fields[CTRLSEQ]);
  2026.        if ( status == 0 )
  2027.       return( FALSE );
  2028.        else
  2029.        {
  2030.          sprintf(msgbuf,
  2031.              "%%  Page %s%s within span starting at {%s {%d}}\n",
  2032.          Entry[idx].item->fields[CTRLSEQ],arg,
  2033.          Entry[PageIndex].item->fields[CTRLSEQ],
  2034.          atoi(Entry[PageIndex].item->fields[NUMBER]));
  2035.     PrintErrorMSG();
  2036.     skippage = TRUE;    
  2037.     return( FALSE );
  2038.        } /* else */
  2039.      } /* if */
  2040.      status = DupPageFormat(idx,arg);
  2041.      if ( !status )
  2042.        return( FALSE );
  2043.      break;
  2044.   } /* switch */
  2045.    
  2046.   RemoveEmptySet(arg);
  2047.  
  2048.   strcpy(prevnum,pagenum);
  2049.   strcpy(pagenum,arg);
  2050.    
  2051.   return(TRUE);
  2052.  
  2053. }
  2054.  
  2055.  
  2056. void PutPageNum(idx)
  2057. int  idx;
  2058. {
  2059. char c;
  2060. char str[80];
  2061.  
  2062.    if ( skippage ) return;
  2063.    
  2064.    c =  *(Entry[idx].item->fields[PAGE_SPAN]) ;
  2065.    switch ( c )
  2066.    {
  2067.       case 'f':
  2068.        sprintf(str,"\\Pagespan %s\n",pagenum);
  2069.        PutString( str, xdxfile );
  2070.        break;
  2071.       case 'F':
  2072.        sprintf(str,"\\PageSpan %s\n",pagenum);
  2073.        PutString( str, xdxfile );
  2074.        break;
  2075.       case 't':
  2076.        sprintf(str,"\\Topage %s\n",pagenum);
  2077.        PutString( str, xdxfile );
  2078.        if ( strcmp( Entry[idx].item->fields[CTRLSEQ],
  2079.                 Entry[PageIndex].item->fields[CTRLSEQ] ) !=0 )
  2080.        {
  2081.         sprintf(msgbuf,"%%  \\Page span from {%s {%d}} to %s\n",
  2082.             Entry[PageIndex].item->fields[CTRLSEQ],
  2083.             atoi(Entry[PageIndex].item->fields[NUMBER]),
  2084.             pagenum);
  2085.         PrintErrorMSG();
  2086.        }
  2087.            PageType = 0; PageIndex = 0; PageSpan = FALSE;
  2088.        break;          
  2089.         default:          
  2090.        sprintf(str,"\\Page %s\n",pagenum);
  2091.        PutString( str, xdxfile );
  2092.            break;
  2093.    }
  2094.    return;
  2095. }
  2096.  
  2097.  
  2098. void GetArgs(idx,arg1,arg2,arg3,arg4,arg5)
  2099. int  idx;
  2100. char *arg1, *arg2, *arg3, *arg4, *arg5;
  2101. {
  2102.    GetArg(idx,arg1,E1_PRE,E1_CS,E1,E1_POST,E1_ALIAS);
  2103.    GetArg(idx,arg2,E2_PRE,E2_CS,E2,E2_POST,E2_ALIAS);
  2104.    GetArg(idx,arg3,E3_PRE,E3_CS,E3,E3_POST,E3_ALIAS);
  2105.    GetArg(idx,arg4,E4_PRE,E4_CS,E4,E4_POST,E4_ALIAS);
  2106.    GetArg(idx,arg5,E5_PRE,E5_CS,E5,E5_POST,E5_ALIAS);
  2107.    return;
  2108. }
  2109.  
  2110.  
  2111. int DupEntry( idx, cur )
  2112. int idx,cur;
  2113. {
  2114.   int i,k,stat;
  2115.   
  2116.  
  2117.   for (i=cur; i<idx; i++)
  2118.   {
  2119.     stat=0;
  2120.     
  2121.     for (k=E1; k<=CROSS_REF && stat==0; k++)
  2122.     {
  2123.      stat=stricmp(Entry[i].item->fields[k],Entry[idx].item->fields[k]);
  2124.     }
  2125.     
  2126.     if ( stat == 0 )
  2127.      return( TRUE );
  2128.     
  2129.   } /* for */
  2130.   
  2131.   if ( stat == 0 )
  2132.        return( TRUE );
  2133.   else return ( FALSE );
  2134.   
  2135. } /* end - DupEntry */
  2136.  
  2137.  
  2138. int DupXref( idx, cur )
  2139. int idx,cur;
  2140. {
  2141.   int i;
  2142.   for (i=idx; i<cur; i++)
  2143.   {
  2144.      if ( stricmp( Entry[i].item->fields[CROSS_REF], 
  2145.                Entry[cur].item->fields[CROSS_REF] ) == 0 )
  2146.       return( TRUE );
  2147.   }
  2148.   
  2149.   return ( FALSE );
  2150.   
  2151. } /* end - DupXref */
  2152.  
  2153.  
  2154. void xxref_proc(idx)
  2155. int  idx;
  2156. {
  2157. int  i,d2,nxt,level,n;
  2158. BYTE done;
  2159. char xtype;
  2160. int  status;
  2161.  
  2162.    /* put out 1 cross reference */
  2163.    GetArgs(idx,arg1,arg2,arg3,arg4,arg5);
  2164.    d2 = GetD2(idx,idx-1);
  2165.    sprintf(msgbuf,"\\Entry %s%d%s%s%s%s%s\n",
  2166.            Entry[idx].item->fields[LARGEST],d2,arg1,arg2,arg3,arg4,arg5);
  2167.    PutString( msgbuf, xdxfile );
  2168.    
  2169.    sprintf(msgbuf,"\\Xref {\\See {%s}}\n",
  2170.        Entry[idx].item->fields[CROSS_REF]);
  2171.    PutString( msgbuf, xdxfile );
  2172.    
  2173.    
  2174.    /* Gather all the cross references */
  2175.    nxt = 1; done = FALSE;
  2176.    while ( !done && (idx+nxt)<=nitems )
  2177.    {
  2178.      level = GetD2(idx,idx+nxt);
  2179.      xtype = (char) *(Entry[idx+nxt].item->fields[XREF]);
  2180.      if ( level==LEVEL5 && ( xtype=='X' || xtype=='x' ) )
  2181.      {
  2182.        if ( !DupXref(idx, idx+nxt) )
  2183.        {
  2184.             sprintf(msgbuf,"\\Morexref {\\See {%s}}\n",
  2185.                 Entry[idx+nxt].item->fields[CROSS_REF]);
  2186.         PutString( msgbuf, xdxfile );
  2187.        }
  2188.        nxt++;
  2189.      }
  2190.      else
  2191.      {
  2192.         done = TRUE;
  2193.      }
  2194.    }
  2195.  
  2196.    SortPageNumber(idx,idx+nxt);
  2197.    n = 0;
  2198.    for ( i=idx; i<idx+nxt; i++)
  2199.    {
  2200.      xtype = (char) *(Entry[i].item->fields[XREF]);
  2201.      if ( xtype != 'x' )
  2202.      {
  2203.        status = GetPageNum(SubPageOrder[n]);
  2204.        if ( status ) PutPageNum(SubPageOrder[n]);
  2205.        n++;
  2206.      }
  2207.    }
  2208.  
  2209.    /* put out cross references again */
  2210.    sprintf(msgbuf,"\\Xref {\\See {%s}}\n",
  2211.            Entry[idx].item->fields[CROSS_REF]);
  2212.    PutString( msgbuf, xdxfile );
  2213.      
  2214.      
  2215.    for ( i=idx+1; i<idx+nxt; i++)
  2216.    {
  2217.      level = GetD2(i,idx);
  2218.      xtype = (char) *(Entry[i].item->fields[XREF]);
  2219.      if ( level==LEVEL5 && ( xtype=='X' || xtype=='x' ) )
  2220.      {
  2221.        if ( !DupXref(idx,i) )
  2222.        {
  2223.             sprintf(msgbuf,"\\Morexref {\\See {%s}}\n",
  2224.                 Entry[i].item->fields[CROSS_REF]);
  2225.         PutString( msgbuf, xdxfile );
  2226.        }
  2227.      } /* if */
  2228.    } /* for */
  2229.    
  2230.    curIndex = idx + nxt;
  2231.    return;
  2232. } /* xxref_proc */
  2233.  
  2234.  
  2235. void xref_proc(idx)
  2236. int  idx;
  2237. {
  2238. int  nxt,level,d2,i;
  2239. BYTE done;
  2240. char xtype;
  2241. BYTE ctype;
  2242.    
  2243.    /* CASE I or CASE II */
  2244.    nxt = 1; done = FALSE; ctype = 1;
  2245.    while ( !done && (idx+nxt)<=nitems )
  2246.    {
  2247.      level = GetD2(idx+nxt,idx);
  2248.      xtype = (char) *(Entry[idx+nxt].item->fields[XREF]);
  2249.      if ( level==LEVEL5 && ( xtype=='X' || xtype =='x') )
  2250.      {
  2251.        if ( xtype == 'X' )
  2252.             ctype = 2;
  2253.        nxt++;
  2254.      }
  2255.      else
  2256.      {
  2257.         done = TRUE;
  2258.      }
  2259.    } /* while */
  2260.  
  2261.  /* CASE I */
  2262.  if ( ctype == 1 )
  2263.  {
  2264.    /* put out 1 cross reference */
  2265.    GetArgs(idx,arg1,arg2,arg3,arg4,arg5);
  2266.    d2 = GetD2(idx,idx-1);
  2267.    
  2268.    sprintf(msgbuf,"\\Entryxref %s%d%s%s%s%s%s{\\See {%s}}\n",
  2269.            Entry[idx].item->fields[LARGEST],d2,arg1,arg2,arg3,arg4,arg5,
  2270.         Entry[idx].item->fields[CROSS_REF]); 
  2271.    PutString( msgbuf, xdxfile );
  2272.    
  2273.  
  2274.    /* Gather up all the cross references */
  2275.    for ( i=idx+1; i<idx+nxt; i++ )
  2276.    {
  2277.      level = GetD2(i,idx);
  2278.      xtype = (char) *(Entry[i].item->fields[XREF]);
  2279.      if ( level==LEVEL5 && xtype=='x' )
  2280.      {
  2281.        if ( !DupXref(idx,i) )
  2282.        {
  2283.                sprintf(msgbuf,"\\Morexref {\\See {%s}}\n",
  2284.                Entry[i].item->fields[CROSS_REF]);
  2285.            PutString( msgbuf, xdxfile );
  2286.        }
  2287.      }
  2288.      else
  2289.      {
  2290.         done = TRUE;
  2291.      }
  2292.    } /* while */
  2293.    
  2294.    curIndex = idx + nxt;
  2295.    
  2296.  } /* if */
  2297.  
  2298.  /* CASE II */
  2299.  else
  2300.  {
  2301.    xxref_proc( idx );
  2302.  }
  2303.  
  2304.    return;
  2305. } /* end  - xref_proc */
  2306.  
  2307.  
  2308. void OutputProc(idx,arg1,arg2,arg3,arg4,arg5)
  2309. int  idx;
  2310. char *arg1, *arg2, *arg3, *arg4, *arg5;
  2311. {
  2312. int d2, status;
  2313.  
  2314.    d2 = GetD2(idx,idx-1);
  2315.    if ( d2==LEVEL5 )
  2316.    {
  2317.       if ( !DupEntry( idx, idx-1 ) )
  2318.       {
  2319.         status = GetPageNum(idx);
  2320.         if ( status )  PutPageNum(idx);
  2321.       }
  2322.    }
  2323.    else
  2324.    {
  2325.      sprintf(msgbuf,"\\Entry %s%d%s%s%s%s%s\n",
  2326.              Entry[idx].item->fields[LARGEST],d2,arg1,arg2,arg3,arg4,arg5);
  2327.      PutString( msgbuf, xdxfile );
  2328.      status = GetPageNum(idx);
  2329.      if ( status ) PutPageNum(idx);
  2330.    }
  2331.    return;    
  2332. } /* end - OutputProc */
  2333.  
  2334.  
  2335. void other_proc(idx)
  2336. int  idx;
  2337. {
  2338. int  i,d2,nxt,level,n;
  2339. BYTE done,first;
  2340. char xtype,ctype;
  2341. int  status;
  2342.  
  2343.  
  2344.    /* this is the last line */
  2345.    if ( idx+1 > nitems )
  2346.    {
  2347.      /* finish up and exits */
  2348.      GetArgs(idx,arg1,arg2,arg3,arg4,arg5);
  2349.      OutputProc(idx,arg1,arg2,arg3,arg4,arg5);
  2350.      curIndex++;
  2351.      return;
  2352.    }
  2353.  
  2354.    /* Get all the LEVEL5 entries */
  2355.    nxt = 1; done = FALSE; ctype = FALSE;
  2356.    while ( !done && (idx+nxt)<=nitems )
  2357.    {
  2358.      level = GetD2(idx+nxt,idx);
  2359.      xtype = (char) *(Entry[idx+nxt].item->fields[XREF]);
  2360.      if ( level==LEVEL5 )
  2361.      {
  2362.     if ( xtype == 'X' || xtype == 'x' )
  2363.        ctype = TRUE;
  2364.         nxt++;
  2365.      }
  2366.      else
  2367.      {
  2368.         done = TRUE;
  2369.      }
  2370.    }
  2371.  
  2372.    if ( !ctype )
  2373.    {
  2374.      /* Not a cross reference, so we output line and return */
  2375.      GetArgs(idx,arg1,arg2,arg3,arg4,arg5);
  2376.      OutputProc(idx,arg1,arg2,arg3,arg4,arg5);
  2377.      curIndex++;
  2378.      return;
  2379.    }
  2380.    
  2381.    /* put out entry first */
  2382.    GetArgs(idx,arg1,arg2,arg3,arg4,arg5);
  2383.    d2 = GetD2(idx,idx-1);
  2384.    sprintf(msgbuf,"\\Entry %s%d%s%s%s%s%s\n",
  2385.            Entry[idx].item->fields[LARGEST],d2,arg1,arg2,arg3,arg4,arg5);
  2386.    PutString( msgbuf, xdxfile );
  2387.  
  2388.    /* Gather all the cross references */
  2389.    first = TRUE;
  2390.    for (i=idx+1; i<idx+nxt; i++ )
  2391.    {
  2392.      level = GetD2(i,idx);
  2393.      xtype = (char) *(Entry[i].item->fields[XREF]);
  2394.      if ( level==LEVEL5 && ( xtype=='X' || xtype=='x' ) )
  2395.      {
  2396.        if ( !DupXref(idx,i) )
  2397.        {
  2398.          if ( first )
  2399.          {
  2400.        first = FALSE;
  2401.            sprintf(msgbuf,"\\Xref {\\See {%s}}\n",
  2402.                Entry[i].item->fields[CROSS_REF]);
  2403.        PutString( msgbuf, xdxfile );
  2404.          } /* if */
  2405.          else
  2406.      {
  2407.            sprintf(msgbuf,"\\Morexref {\\See {%s}}\n",
  2408.                Entry[i].item->fields[CROSS_REF]);
  2409.        PutString( msgbuf, xdxfile );
  2410.          } /* else */
  2411.        } /* if - dupXref */
  2412.      } /* if - level */
  2413.    } /* for */
  2414.  
  2415.  
  2416.    /* We need to sort a subset of the entries base on page order,
  2417.       viz, entries with LEVEL5 */
  2418.    SortPageNumber(idx,idx+nxt);
  2419.    
  2420.    n = 0;
  2421.    for ( i=idx; i<idx+nxt; i++)
  2422.    {
  2423.      xtype = (char) *(Entry[i].item->fields[XREF]);
  2424.      switch ( xtype )
  2425.      {
  2426.       case 'x':
  2427.        break;
  2428.       case 'X':
  2429.       default:
  2430.         status = GetPageNum(SubPageOrder[n]);
  2431.         if ( status ) PutPageNum(SubPageOrder[n]);
  2432.     n++;
  2433.     break;
  2434.     } /* switch */
  2435.    } /* for */
  2436.  
  2437.    /* put out cross references again */
  2438.    first  = TRUE;
  2439.    for ( i=idx+1; i<idx+nxt; i++)
  2440.    {
  2441.      level = GetD2(i,idx);
  2442.      xtype = (char) *(Entry[i].item->fields[XREF]);
  2443.      if ( level==5 && ( xtype=='X' || xtype=='x' ) )
  2444.      {
  2445.        if ( !DupXref(idx,i) )
  2446.        {
  2447.          if ( first )
  2448.          {
  2449.           sprintf(msgbuf,"\\Xref {\\See {%s}}\n",
  2450.               Entry[i].item->fields[CROSS_REF]);
  2451.       PutString( msgbuf, xdxfile );
  2452.       first = FALSE;
  2453.          } /* if */
  2454.          else
  2455.      {
  2456.           sprintf(msgbuf,"\\Morexref {\\See {%s}}\n",
  2457.               Entry[i].item->fields[CROSS_REF]);
  2458.       PutString( msgbuf, xdxfile );
  2459.          } /* else */
  2460.        } /* if */
  2461.       } /* if */
  2462.    } /* for */
  2463.  
  2464.    curIndex = idx + nxt;
  2465.    return;
  2466. } /* end - other_proc */
  2467.  
  2468.  
  2469. void TeXPut(idx)
  2470. int  idx;
  2471. {
  2472. char xtype;
  2473.  
  2474.     curLetter = (char) toupper(*(Entry[idx].item->fields[E1]));
  2475.     if ( curLetter != preLetter )
  2476.     {
  2477.          sprintf(msgbuf,"\n\\LETTER %c\n\n",curLetter);
  2478.      PutString( msgbuf, xdxfile );
  2479.          preLetter = curLetter;
  2480.     }
  2481.  
  2482.     xtype = (char) *(Entry[idx].item->fields[XREF]);
  2483.     
  2484.     switch( xtype )
  2485.     {
  2486.        case 'x':
  2487.         xref_proc(idx);
  2488.         break;
  2489.        case 'X':
  2490.         xxref_proc(idx);
  2491.         break;
  2492.        default:
  2493.         other_proc(idx);
  2494.         break;
  2495.     }
  2496.     
  2497.     return;
  2498. } /* end - TeXPut */
  2499.  
  2500.  
  2501.  
  2502. void TeXOut()
  2503. {
  2504.   int  i;
  2505.   
  2506.   printMSG("writing output...");
  2507.   preLetter = 0;
  2508.   for (i=0; i<ndef; i++)
  2509.   {
  2510.      sprintf(msgbuf,"%s\n",define[i]);
  2511.      PutString( msgbuf, xdxfile );
  2512.   } /* for */
  2513.  
  2514.   curIndex = 1;
  2515.   while ( curIndex <= nitems )
  2516.   {
  2517.      TeXPut( curIndex ); 
  2518.   }
  2519.   return;
  2520. } /* end - TexOut */
  2521.  
  2522.  
  2523. /**********************************************************************/
  2524. /* Move Entries                                                  */
  2525. /* Inputs: from, to                                          */
  2526. /* Output: none                                          */
  2527. /**********************************************************************/
  2528. void MoveEntry(from,to)
  2529.  int from,to;
  2530. {
  2531. int k;
  2532.  
  2533.   /* return if both are the same entry */
  2534.   if ( from == to )
  2535.        return;
  2536.  
  2537.   for (k=E1; k<=CROSS_REF; k++)
  2538.   {
  2539.      Entry[to].item->fields[k] = Entry[from].item->fields[k];
  2540.   }
  2541.   
  2542.   return;
  2543. } /* end - MoveEntry */
  2544.  
  2545.  
  2546. /**********************************************************************/
  2547. /* Free Entry                                                  */
  2548. /* Inputs: idx                                              */
  2549. /* Output: none                                          */
  2550. /**********************************************************************/
  2551. void FreeEntry(idx)
  2552.  int idx;
  2553. {
  2554. int j;
  2555.  
  2556.   if ( Entry[idx].item!=NULL )
  2557.   {
  2558.     for ( j=E1; j<=CROSS_REF; j++ )
  2559.     {
  2560.      if ( Entry[idx].item->fields[j]!=NULLPTR )
  2561.       free( Entry[idx].item->fields[j] );
  2562.      Entry[idx].item->fields[j] = NULLPTR;
  2563.     }
  2564.   }
  2565.   
  2566.   return;
  2567.   
  2568. } /* end - FreeEntry */
  2569.  
  2570.  
  2571. /**********************************************************************/
  2572. /* Remove Duplicates Entries                                          */
  2573. /* Inputs: none                                              */
  2574. /* Output: modified nitems                                  */
  2575. /**********************************************************************/
  2576. void RemoveDuplicates()
  2577. {
  2578.   int i,j,cur,level;
  2579.  
  2580.   cur = 1;
  2581.   for ( i=2; i<=nitems; i++ )
  2582.   {
  2583.      if ( DupEntry( i, cur ) )
  2584.      {
  2585.     Entry[i].item->fields[0] = DELPTR;
  2586.      }
  2587.      level = GetD2(i,cur);
  2588.      if ( level!=LEVEL5 )
  2589.       cur = i;
  2590.   }
  2591.  
  2592.   for ( i=1,j=1; i<=nitems; i++ )
  2593.   {
  2594.      if ( Entry[i].item->fields[0]==DELPTR )
  2595.      {
  2596.     FreeEntry(i);
  2597.      }
  2598.      else
  2599.      {
  2600.     MoveEntry(i,j);
  2601.     j++;
  2602.      }
  2603.   }
  2604.   
  2605.   nitems = --j;
  2606.   
  2607.   return;
  2608. } /* end - RemoveDuplicates */
  2609.  
  2610. /* make main() an int so it returns something predictable to the OS */
  2611. int main(argc, argv)
  2612. int  argc;
  2613. char *argv[];
  2614. {
  2615.     
  2616.   if ( argc<2 )
  2617.    {
  2618.       printf("\n\tUsage: index filename\n");
  2619.       exit(0);
  2620.    }
  2621.  
  2622.    printf("\n\tnewindex 1.10    All Rights Reserved.");
  2623.    printf("\n\tCopyright (c) 1989-91 The TeXplorators Corporation.\n");
  2624.       
  2625.    strcpy(ndxname,argv[1]); strcat(ndxname,".ndx");
  2626.    strcpy(tmpname,argv[1]); strcat(tmpname,".@d@");
  2627.    strcpy(xdxname,argv[1]); strcat(xdxname,".xdx");
  2628.    strcpy(idxname,argv[1]); strcat(idxname,".idx");
  2629.  
  2630.    idxfile = FALSE;
  2631.    if ( argc > 2 )
  2632.    {
  2633.       if ( strnicmp(argv[2],"-i",2)==0 )
  2634.        idxfile = TRUE;
  2635.    }
  2636.     
  2637.    if ( ( ndxfile = fopen(ndxname,"r") )==NULL )
  2638.    {
  2639.       printf("File %s not found\r\n",ndxname);
  2640.       beep();
  2641.       exit(0);
  2642.    }
  2643.   
  2644.    if ( ( xxxfile = fopen(tmpname,"w+") )==NULL )
  2645.    {
  2646.      printf("File %s cannot be opened\r\n",tmpname);
  2647.      beep();
  2648.      exit(0);
  2649.    }
  2650.  
  2651.    if ( ( xdxfile = fopen(xdxname,"w") )==NULL )
  2652.    {
  2653.      printf("File %s cannot be opened\r\n",xdxname);
  2654.      beep();
  2655.      exit(0);
  2656.    }
  2657.    
  2658.    InitProc();
  2659.  
  2660.    PreProc();
  2661.  
  2662.    BuildProc();
  2663.    
  2664.    fclose(ndxfile);
  2665.  
  2666.    SortProc();
  2667.    
  2668.    RemoveDuplicates();
  2669.  
  2670.    TeXOut();
  2671.    
  2672.    fclose(xdxfile);
  2673.    fclose(xxxfile);
  2674. #ifdef MICROSOFTC
  2675.    fcloseall();
  2676. #endif
  2677.  
  2678.    unlink(tmpname);
  2679.    FreeMem();
  2680.    
  2681.    printMSG("");
  2682.    printf("\r\n");
  2683.    
  2684.    return(0);
  2685. }
  2686.  
  2687.  
  2688. /* ############################### END OF FILE ########################### */
  2689.